package org.walkerljl.commons.security;

import org.walkerljl.commons.log.Logger;
import org.walkerljl.commons.log.LoggerFactory;
import org.walkerljl.commons.util.ArraysUtils;
import org.walkerljl.commons.util.LongUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 服务调用安全校验器
 *
 * 防止数据篡改、消息重放
 *
 * @author lijunlin
 */
public final class ServiceInvokeSecurityValidator {

    private static final Logger LOGGER = LoggerFactory.getLogger(ServiceInvokeSecurityValidator.class);

    /**
     * 超时时间，单位：毫秒
     */
    private long timeout = 0;

    /**
     * 构造函数
     */
    public ServiceInvokeSecurityValidator() {}

    /**
     * 构造函数
     *
     * @param timeout 超时时间，单位：毫秒
     */
    public ServiceInvokeSecurityValidator(long timeout) {
        this.timeout = timeout;
    }

    /**
     * 生成签名
     *
     * @param appId 应用ID
     * @param token token
     * @param timestamp 时间戳
     * @param nonce 随机数
     * @param bussinessParams 业务参数
     * @return
     */
    public String generateSignature(String appId, String token, String timestamp, String nonce, String[] bussinessParams) {
        String[] arrTmp = null;
        if (ArraysUtils.isEmpty(bussinessParams)) {
            arrTmp = new String[]{appId, token, timestamp, nonce};
        } else {
            int capacity = 4 + bussinessParams.length;
            List<String> list = new ArrayList<String>(capacity);
            list.add(appId);
            list.add(token);
            list.add(timestamp);
            list.add(nonce);
            for (String bussinessParam : bussinessParams) {
                list.add(bussinessParam);
            }
            arrTmp = new String[capacity];
            list.toArray(arrTmp);
        }
        Arrays.sort(arrTmp);
        StringBuilder sb = new StringBuilder();
        for (String str : arrTmp) {
            sb.append(str);
        }
        String signature = EncryptUtils.encryptByMD5(sb.toString());
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug(String.format("Do generate,appId:%s,token:%s,timestamp:%s,nonce:%s,bussinessParams:%s->%s.",
                    appId, token, timestamp, nonce, ArraysUtils.toString(bussinessParams), signature));
        }
        return signature;
    }

    /**
     * 生成签名
     *
     * @param appId 应用ID
     * @param token token
     * @param timestamp 时间戳
     * @param nonce 随机数
     * @return
     */
    public String generateSignature(String appId, String token, String timestamp, String nonce) {
        return generateSignature(appId, token, timestamp, nonce, null);
    }

    /**
     *
     * 校验签名
     *
     *@param signature 待校验的签名
    * @param appId 应用ID
    * @param token token
    * @param timestamp 时间戳
    * @param nonce 随机数
    * @param bussinessParams 业务参数
    */
    public boolean validateSignature(String signature, String appId, String token, String timestamp, String nonce, String[] bussinessParams) {
        boolean result = false;
        if (timeout <= 0 || (System.currentTimeMillis() - LongUtils.parseLong(timestamp)) <= timeout) {
            String expectedSignature = generateSignature(appId, token, timestamp, nonce, bussinessParams);
            if (expectedSignature.equals(signature)) {
                result = true;
            }
        }
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug(String.format("Do validate,signature:%s,appId:%s,token:%s,timestamp:%s,nonce:%s,bussinessParams:%s->%s.",
                    signature, appId, token, timestamp, nonce, ArraysUtils.toString(bussinessParams), result));
        }
        return result;
    }

    /**
     *
     * 校验签名
     *
     *@param signature 待校验的签名
     * @param appId 应用ID
     * @param token token
     * @param timestamp 时间戳
     * @param nonce 随机数
     */
    public boolean validateSignature(String signature, String appId, String token, String timestamp, String nonce) {
        return validateSignature(signature, appId, token, timestamp, nonce, null);
    }
}